package com.liuym.classes.service.impl;

import com.liuym.classes.common.LogAndExceptionCommon;
import com.liuym.classes.repository.mapper.ClassScoreMapper;
import com.liuym.classes.repository.model.bo.ClassBO;
import com.liuym.classes.repository.model.bo.ClassScoreBO;
import com.liuym.classes.repository.model.bo.ClassScoreBatchBO;
import com.liuym.classes.repository.model.entity.ClassScore;
import com.liuym.classes.service.ClassScoreService;
import com.liuym.classes.service.ClassService;
import com.liuym.common.constants.ResponseCodeConstants;
import com.liuym.common.dubbo.classes.dto.ClassScoreDTO;
import com.liuym.common.exception.ClassException;
import com.vip.vjtools.vjkit.mapper.BeanMapper;
import io.swagger.models.auth.In;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author Liuym
 * @date 2019/1/3 15:16
 * @describe：
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class ClassScoreServiceImpl implements ClassScoreService {

    @Autowired
    private ClassScoreMapper classScoreMapper;

    @Autowired
    private ClassService classService;



    @Override
    public void updateClassScore(String classScoreTableName, ClassScoreBO classScoreBO, Integer oldScore) throws ClassException {
        ClassBO classBO = classService.getClassByNumber(classScoreBO.getClassNumber());
        classBO.setScore(classBO.getScore()-oldScore+classScoreBO.getFinallyScore());
        classService.updateClass(classBO);
        classScoreMapper.updateClassScore(classScoreTableName, BeanMapper.map(classScoreBO, ClassScore.class));
    }


    @Override
    public boolean addClassScore(String classScoreTableName, String userName, ClassScoreBO classScoreBO) throws ClassException {
        baseParamCheck(classScoreBO);
        classScoreBO.setOperateDate(new Date());
        classScoreBO.setOperator(userName);
        int insertClassScore = classScoreMapper.insertSelective(classScoreTableName, BeanMapper.map(classScoreBO, ClassScore.class));
        //更新class表字段
        int updateScoreByClassNumber = classService.updateScoreByClassNumber(classScoreBO.getFinallyScore(), classScoreBO.getClassNumber());
        if (insertClassScore > 0 && updateScoreByClassNumber > 0) {
            return true;
        }
        return false;
    }

    @Override
    public Map<String, Object> addClassScoreBatch(String classScoreTableName, String userName, List<ClassScoreBO> classScoreBOList) throws ClassException {
        {
            Map<String, Object> map = new HashMap<String, Object>();
            List failList = new ArrayList(); //存脏数据数据
            List<ClassScore> classScoreList = new ArrayList<ClassScore>();
            List<ClassScoreDTO> failClassScoreList = new ArrayList<ClassScoreDTO>();
            int failResult = 0; //验证不通过数量
            for (ClassScoreBO classScoreBO : classScoreBOList) {
                String checkExcelParam = checkExcelParam(classScoreBO);
                if ("验证通过".equals(checkExcelParam)) {
                    ClassScore classScore = BeanMapper.map(classScoreBO, ClassScore.class);
                    classScoreList.add(classScore);
                } else {
                    failResult++;
                    failList.add(checkExcelParam);
                    failClassScoreList.add(BeanMapper.map(classScoreBO, ClassScoreDTO.class));
                }
            }
            map.put("failResult", failResult);
            map.put("failReason", failList);
            map.put("failClassScore", failClassScoreList);
            //开始批量存入t_stucent_score表
            if (0 < classScoreList.size()) {
                //限制每批存储大小
                int limitDataNumber = 200;
                int size = classScoreList.size();
                List<ClassScoreBatchBO> classScoreBatchBOList = null;
                if (size < limitDataNumber) {
                    classScoreMapper.addClassScoreList(classScoreTableName, classScoreList);
                    classScoreBatchBOList =
                            classScoreList
                                    .stream()
                                    .map(s -> BeanMapper.map(s, ClassScoreBatchBO.class))
                                    .collect(Collectors.toList());
                    //批量更新t_class的f_score字段
                    //1.先分组
                    List<ClassScoreBatchBO> groupClassScore = getGroupClassScore(classScoreBatchBOList);
                    //2.再更新
                    classService.updateScoreByClassNumberBatch(groupClassScore);
                } else {
                    // 分批数
                    int part = size / limitDataNumber;
                    for (int i = 0; i < part; i++) {
                        List<ClassScore> classScoreListPart =
                                classScoreList.subList(0, limitDataNumber);
                        classScoreMapper.addClassScoreList(classScoreTableName, classScoreListPart);
                        classScoreBatchBOList =
                                classScoreListPart
                                        .stream()
                                        .map(s -> BeanMapper.map(s, ClassScoreBatchBO.class))
                                        .collect(Collectors.toList());
                        //批量更新t_class的f_score字段
                        //1.先分组
                        List<ClassScoreBatchBO> groupClassScore = getGroupClassScore(classScoreBatchBOList);
                        //2.再更新
                        classService.updateScoreByClassNumberBatch(groupClassScore);
                        // 剔除
                        classScoreList.subList(0, limitDataNumber).clear();
                    }
                    if (!classScoreList.isEmpty()) {
                        // 存入剩下的
                        classScoreMapper.addClassScoreList(classScoreTableName, classScoreList);
                        classScoreBatchBOList =
                                classScoreList
                                        .stream()
                                        .map(s -> BeanMapper.map(s, ClassScoreBatchBO.class))
                                        .collect(Collectors.toList());
                        //批量更新t_class的f_score字段
                        //1.先分组
                        List<ClassScoreBatchBO> groupClassScore = getGroupClassScore(classScoreBatchBOList);
                        //2.再更新
                        classService.updateScoreByClassNumberBatch(groupClassScore);
                    }
                }
            }
            return map;
        }
    }

    private List<ClassScoreBatchBO> getGroupClassScore(List<ClassScoreBatchBO> classScoreBatchBOList) {
        Map<Long, LongSummaryStatistics> collect = classScoreBatchBOList.stream().collect(
                Collectors.groupingBy(ClassScoreBatchBO::getClassNumber,
                        Collectors.summarizingLong(ClassScoreBatchBO::getFinallyScore)));
        classScoreBatchBOList.clear();
        //2.再更新
        ClassScoreBatchBO classScoreBatchBO;
        for (Map.Entry<Long, LongSummaryStatistics> entry : collect.entrySet()) {
            Long key = entry.getKey();
            LongSummaryStatistics finallyScore = entry.getValue();
            classScoreBatchBO = new ClassScoreBatchBO();
            classScoreBatchBO.setClassNumber(key);
            classScoreBatchBO.setFinallyScore((int) finallyScore.getSum());
            classScoreBatchBOList.add(classScoreBatchBO);
        }
        return classScoreBatchBOList;
    }

    @Override
    public List<ClassScoreBO> getClassScoreByNumber(String classScoreTableName, long classNumber) throws ClassException {
        List<ClassScore> classScoreList = classScoreMapper.getClassScoreByClassNumber(classScoreTableName, classNumber);
        if (classScoreList != null && classScoreList.size() > 0) {
            // jdk1.8实现list类型转换
            List<ClassScoreBO> classScoreBOList =
                    classScoreList
                            .stream()
                            .map(s -> BeanMapper.map(s, ClassScoreBO.class))
                            .collect(Collectors.toList());
            return classScoreBOList;
        }
        return null;
    }

    @Override
    public ClassScoreBO getClassScoreById(String classScoreTableName, int id) throws ClassException {
        ClassScore classScore = classScoreMapper.selectByPrimaryKey(classScoreTableName, id);
        if (classScore != null) {
            return BeanMapper.map(classScore, ClassScoreBO.class);
        }
        return null;
    }

    @Override
    public void deleteClassScore(String classScoreTableName, int id) throws ClassException {
        ClassScoreBO classScoreBO = getClassScoreById(classScoreTableName, id);
        classService.updateScoreByClassNumber(-classScoreBO.getFinallyScore(), classScoreBO.getClassNumber());
        classScoreMapper.deleteClassScore(classScoreTableName, id);
    }

    @Override
    public void deleteClassScoreByNumber(String classScoreTableName, long classNumber) throws ClassException {
        classScoreMapper.deleteClassScoreByNumber(classScoreTableName, classNumber);
    }

    @Override
    public List<ClassScoreBO> getClassScoreByTime(String classScoreTableName, Date startTime, Date endTime) throws ClassException {
        List<ClassScore> classScoreList = classScoreMapper.getClassScoreByTime(classScoreTableName, startTime, endTime);
        if (classScoreList != null && classScoreList.size() > 0) {
            // jdk1.8实现list类型转换
            List<ClassScoreBO> classScoreBOList =
                    classScoreList
                            .stream()
                            .map(s -> BeanMapper.map(s, ClassScoreBO.class))
                            .collect(Collectors.toList());
            return classScoreBOList;
        }
        return null;
    }

    @Override
    public List<ClassScoreBO> getClassScoreByAdmin(String classScoreTableName, String userName, Date startTime, Date endTime) throws ClassException {
        List<ClassScore> classScoreList = classScoreMapper.getClassScoreByAdmin(classScoreTableName, userName, startTime, endTime);
        if (classScoreList != null && classScoreList.size() > 0) {
            // jdk1.8实现list类型转换
            List<ClassScoreBO> classScoreBOList =
                    classScoreList
                            .stream()
                            .map(s -> BeanMapper.map(s, ClassScoreBO.class))
                            .collect(Collectors.toList());
            return classScoreBOList;
        }
        return null;
    }

    @Override
    public int addClassScoreTable(String classScoreTableName) throws ClassException {
        StringBuffer stringBuffer = new StringBuffer(classScoreTableName);
        int result = 0;
        try {
            result = classScoreMapper.addClassScoreTable(classScoreTableName);
        } catch (Exception e) {
            LogAndExceptionCommon.recordLogAndThrowExceptionByWarn(
                    ResponseCodeConstants.DONOT_REOPERATION_CODE,
                    ResponseCodeConstants.DONOT_REOPERATION_MSG,
                    "");
        }
        return result;
    }


    /**
     * 检查参数
     *
     * @param classScoreBO
     * @return
     * @throws ClassException
     */
    private void baseParamCheck(ClassScoreBO classScoreBO) throws ClassException {
        if (null == classScoreBO.getClassNumber()) {
            LogAndExceptionCommon.recordLogAndThrowExceptionByWarn(
                    ResponseCodeConstants.CLASSNUMBER_IS_NOT_NULL_CODE,
                    ResponseCodeConstants.CLASSNUMBER_IS_NOT_NULL_MSG,
                    "");
        }
        if (null == classScoreBO.getApplyScore()) {
            LogAndExceptionCommon.recordLogAndThrowExceptionByWarn(
                    ResponseCodeConstants.APPLYSCORE_IS_NOT_NULL_CODE,
                    ResponseCodeConstants.APPLYSCORE_IS_NOT_NULL_MSG,
                    "");
        }
        if (null == classScoreBO.getFinallyScore()) {
            LogAndExceptionCommon.recordLogAndThrowExceptionByWarn(
                    ResponseCodeConstants.FINALSCORE_IS_NOT_NULL_CODE,
                    ResponseCodeConstants.FINALSCORE_IS_NOT_NULL_MSG,
                    "");
        }
        if (null == classScoreBO.getDate()) {
            LogAndExceptionCommon.recordLogAndThrowExceptionByWarn(
                    ResponseCodeConstants.APPLY_DATE_NOT_NULL_CODE,
                    ResponseCodeConstants.APPLY_DATE_NOT_NULL_MSG,
                    "");
        }
        if (null == classScoreBO.getReason()) {
            LogAndExceptionCommon.recordLogAndThrowExceptionByWarn(
                    ResponseCodeConstants.REASON_IS_NOT_NULL_CODE,
                    ResponseCodeConstants.REASON_IS_NOT_NULL_MSG,
                    "");
        }
        if (null == classScoreBO.getPage()) {
            LogAndExceptionCommon.recordLogAndThrowExceptionByWarn(
                    ResponseCodeConstants.PAGE_IS_NOT_NULL_CODE,
                    ResponseCodeConstants.PAGE_IS_NOT_NULL_MSG,
                    "");
        }
    }

    private String checkExcelParam(ClassScoreBO classScoreBO) throws ClassException {
        if (null == classScoreBO.getClassNumber() || "".equals(classScoreBO.getClassNumber())) {
            return "班号不能为空！";
        }
        if (null == classScoreBO.getApplyScore() || "".equals(classScoreBO.getApplyScore())) {
            return "申请分数不能为空！";
        }
        if (null == classScoreBO.getFinallyScore() || "".equals(classScoreBO.getFinallyScore())) {
            return "最终不能为空！";
        }
        if (null == classScoreBO.getReason() || "".equals(classScoreBO.getReason())) {
            return "申请原因不能为空！";
        }
        if (null == classScoreBO.getPage() || "".equals(classScoreBO.getPage())) {
            return "页码不能为空！";
        }
        if (null == classScoreBO.getDate() || "".equals(classScoreBO.getDate())) {
            return "申请时间不能为空！";
        }
        return "验证通过";
    }

}
